/****************************************************************************************
*                                                                                      *
*                          Projeto BioInfo - Lincs and CIn / UFPE                      *
*                                    07/10/2014                                        *
*																					   *
****************************************************************************************
* Descricao: Arquivo que contem main da classe Threads.                    *
****************************************************************************************
* Responsaveis: Jefferson Ramos (jrla)													   *
*                                                                                      */
/*                                                                                     *
****************************************************************************************/
#include <Threads.hpp>
#include <TicToc.hpp>

#define PRINT_TAXA

using namespace std;

int main(int argc, char **argv) {

	int NUM_THREADS = 10;
	int TAMSEQ = 240;
	int alignment_by_individuals = 15;
	int alignment_by_threads = 1;
	int num_individuals = 2500;
	int query_compare = 1;
	int run_times = 1;

	//if (argc == 7)
	//{
	//	NUM_THREADS = atoi(argv[1]);
	//	TAMSEQ = atoi(argv[2]);
	//	alignment_by_individuals = atoi(argv[3]);
	//	num_individuals = atoi(argv[4]);
	//	query_compare = atoi(argv[5]);
	//	run_time = atoi(argv[6]);
	//}
	//else{
	//	printf("Usage: %s Default\n", argv[0]);
	//	exit(0);
	//}

	Threads *bioinfo_threads = NULL;

	try{

		bioinfo_threads = new Threads(
										NUM_THREADS,
										TAMSEQ,
										alignment_by_individuals,
										num_individuals,
										query_compare,
										run_times
										);
	}
	catch ( ... ){
		printf("ERRO: Falha ao inicializar Threads.");
		printf("\n\nPressione ENTER para continuar...");
		getchar();
		exit(-1);
	}

	cout << "\nPress ENTER to run Threads:" << endl;
	fflush(stdin);
	getchar();

	TictocAverage tt;

	fopen_s(&bioinfo_threads->BD_nucleotideos, "../files/BD_out_bin.bin", "rb");
	if (bioinfo_threads->BD_nucleotideos == NULL){
		printf("\nError: No open file threads_BD_nucleotideos\n");
		getchar();
	}

	int m, i, j;
	int max_individuals = num_individuals;
	int alocation_max_ind = 200000;

	m = num_individuals / alocation_max_ind;

	if (num_individuals >= alocation_max_ind)
		num_individuals = alocation_max_ind;
	else
		alocation_max_ind = num_individuals;

	//passando numero maximo de individuos para objeto do Canonic
	bioinfo_threads->set_num_individuals(alocation_max_ind);

	// Vectors Allocation
	if (bioinfo_threads->vectors_malloc()){ printf("ERROR: vectors_malloc\n"); exit(-1); }

	// Read Input Query Files and Rewind File
	bioinfo_threads->read_input_query();
	rewind(bioinfo_threads->BD_nucleotideos);

	cout << "Executando Threads: " << run_times << " rodada(s)\n" << endl;

	bioinfo_threads->time_average = 0.0;
	for (j = 0; j < run_times; j++){
		bioinfo_threads->sum_time = 0.0;

		//passando numero maximo de individuos para objeto do Canonic
		bioinfo_threads->set_num_individuals(alocation_max_ind);

		for (i = 0; i < m; i++){

			// Threads multiplo dos individuos (Get MMC)
			alignment_by_threads = ceil( (float) alocation_max_ind / NUM_THREADS );
			alignment_by_threads *= alignment_by_individuals;

			//passando alignment_by_threads para objeto do Threads
			bioinfo_threads->set_alignment_by_threads(alignment_by_threads);

			bioinfo_threads->read_input_individuals(); // Read Input Individuals Files

			tt.Tic();
			bioinfo_threads->run(); // Run NeedleMan Canonic and Threads
			bioinfo_threads->sum_time += tt.Toc();

#ifdef PRINT_TAXA// Taxa Output Files
			bioinfo_threads->print_results();
#endif
		}
		if((max_individuals-alocation_max_ind*i) > 0)
		{

			//passando numero maximo de individuos para objeto do Canonic
			bioinfo_threads->set_num_individuals(max_individuals - alocation_max_ind*m);

			// Threads multiplo dos individuos restantes (Get MMC)
			alignment_by_threads = ceil( (float) (max_individuals - alocation_max_ind*m) / NUM_THREADS );
			alignment_by_threads *= alignment_by_individuals;

			//passando alignment_by_threads para objeto do Threads
			bioinfo_threads->set_alignment_by_threads(alignment_by_threads);

			bioinfo_threads->read_input_individuals(); // Read Input Individuals Files

			tt.Tic();
			bioinfo_threads->run(); // Run NeedleMan Canonic and Threads
			bioinfo_threads->sum_time += tt.Toc();

#ifdef PRINT_TAXA// Taxa Output Files
			bioinfo_threads->print_results();
#endif
		}

		bioinfo_threads->time_average += bioinfo_threads->sum_time;
		printf("Rodada: %d Tempo: %.2f ms\n", j + 1, bioinfo_threads->sum_time * 1000);

		rewind(bioinfo_threads->BD_nucleotideos);

#ifdef PRINT_TAXA
		rewind(bioinfo_threads->TaxaOut);
#endif
	}
	fprintf(bioinfo_threads->Results, "Threads - NUM_INDIVIDUALS: %d\n", max_individuals);
	fprintf(bioinfo_threads->Results, "Tempo medio: %.2f ms\n\n", bioinfo_threads->time_average * 1000 / run_times);
	printf("Tempo medio: %.2f ms\n\n", bioinfo_threads->time_average * 1000 / run_times);

	cout << "\nPress ENTER to exit Threads:" << endl;
	fflush(stdin);
	getchar();

	return 0;
}